/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * This file contains relicensed code from Apache copyright of 
 * Copyright (C) 2006 The Android Open Source Project
 */

package com.cloudptt.api.pjsip.utils;

import com.cloudptt.api.product.device.DeviceInfo;
import com.cloudptt.api.product.log.Log;

import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Vibrator;

/**
 * Ringer manager for the Phone app.
 */
public class Ringer {
    private static final String THIS_FILE = "Ringer";
    public static final int PROGRESS_RING = 0;
    public static final int PROGRESS_NOTIFY = 1;
   
    private static final int VIBRATE_LENGTH = 1000; // ms
    private static final int PAUSE_LENGTH = 1000; // ms

    // Uri for the ringtone.
    Uri customRingtoneUri;

//    Vibrator vibrator;
//    VibratorThread vibratorThread;
    HandlerThread ringerThread;
    Context context;

    private RingWorkerHandler ringerWorker;

    public Ringer(Context aContext) {
        context = aContext;
//        vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        ringerThread = new HandlerThread("RingerThread");
        ringerThread.start();
        ringerWorker = new RingWorkerHandler(ringerThread.getLooper());
    }

    /**
     * Starts the ringtone and/or vibrator. 
     * 
     */
    public void ring(int type,String defaultRingtone) {
        Log.d(THIS_FILE, "==> ring() called...");

        synchronized (this) {

        	AudioManager audioManager =
                (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        	
        	//Save ringtone at the begining in case we raise vol
            Ringtone ringtone = getRingtone(defaultRingtone);
            ringerWorker.setRingtone(ringtone);
            
        	//No ring no vibrate
//            int ringerMode = audioManager.getRingerMode();
//            if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
//            	Log.d(THIS_FILE, "skipping ring and vibrate because profile is Silent");
//            	return;
//            }
            
            // Vibrate
//            int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
//            Log.d(THIS_FILE, "v=" + vibrateSetting + " rm=" + ringerMode);
//            if (vibratorThread == null) {
//                vibratorThread = new VibratorThread();
//                Log.d(THIS_FILE, "Starting vibrator...");
//                vibratorThread.start();
//            }

            // Vibrate only
//            if (ringerMode == AudioManager.RINGER_MODE_VIBRATE ||
//            		audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0 ) {
//            	Log.d(THIS_FILE, "ringerMode="+ringerMode + ",Volume=" + 
//            		audioManager.getStreamVolume(AudioManager.STREAM_RING));
//            	if( ringerMode == AudioManager.RINGER_MODE_VIBRATE )
//            	{
//            	Log.d(THIS_FILE, "skipping ring because profile is Vibrate OR because volume is zero");
//            	return;
//            	}
//            	audioManager.setStreamVolume( AudioManager.STREAM_RING, 
//            			audioManager.getStreamMaxVolume(AudioManager.STREAM_RING), 0 );
//            }

            // Ringer normal, audio set for ring, do it
            if(ringtone == null) {
            	Log.d(THIS_FILE, "No ringtone available - do not ring");
            	return;
            }

            ringerWorker.startRinging(type,audioManager);
        	
        }
    }

    /**
     * @return true if we're playing a ringtone and/or vibrating
     *     to indicate that there's an incoming call.
     *     ("Ringing" here is used in the general sense.  If you literally
     *     need to know if we're playing a ringtone or vibrating, use
     *     isRingtonePlaying() or isVibrating() instead.)
     */
    public boolean isRinging() {
    	return (!ringerWorker.isStopped());
    }
    
    /**
     * Stops the ringtone and/or vibrator if any of these are actually
     * ringing/vibrating.
     */
	public void stopRing() {
		synchronized (this) {
			Log.d(THIS_FILE, "==> stopRing() called...");
//			stopVibrator();
			stopRinger();
		}
	}
    
    
	private void stopRinger() {
	    ringerWorker.askStop();
	}
    
//	private void stopVibrator() {
//
//		if (vibratorThread != null) {
//			vibratorThread.interrupt();
//			try {
//				vibratorThread.join(250); // Should be plenty long (typ.)
//			} catch (InterruptedException e) {
//			} // Best efforts (typ.)
//			vibratorThread = null;
//		}
//	}

//	public void updateRingerMode() {
//
//		AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//		synchronized (this) {
//			int ringerMode = audioManager.getRingerMode();
//			// Silent : stop everything
//			if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
//				stopRing();
//				return;
//			}
//
//			// Vibrate
////			int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
//			// If not already started restart it
//			if (vibratorThread == null) {
//				vibratorThread = new VibratorThread();
//				vibratorThread.start();
//			}
//
//			// Vibrate only
////			if (ringerMode == AudioManager.RINGER_MODE_VIBRATE || audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
////				stopRinger();
////				return;
////			}
//
//            //Ringer
//			ringerWorker.startRinging(audioManager);
//		}
//	}

//    private class VibratorThread extends Thread {
//        public void run() {
//        	try {
//	            while (true) {
//	                vibrator.vibrate(VIBRATE_LENGTH);
//	                Thread.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);
//	            }
//        	} catch (InterruptedException ex) {
//        		Log.d(THIS_FILE, "Vibrator thread interrupt");
//        	} finally {
//        		vibrator.cancel();
//        	}
//    		Log.d(THIS_FILE, "Vibrator thread exiting");
//        }
//    }

    /**
     * Thread worker class that handles the task playing ringtone
     */
    private class RingWorkerHandler extends Handler {

        private Boolean askedStopped = false;
        private Ringtone ringtone = null;

        public RingWorkerHandler(Looper looper) {
            super(looper);
        }
        
        /**
         * @param audioManager 
         * 
         */
        public void startRinging(int type,AudioManager audioManager) {
            if(ringtone != null) {
                Log.d(THIS_FILE, "Starting ring with " + ringtone.getTitle(context));
                Message msg = ringerWorker.obtainMessage(type);
                msg.arg1 = type;
                Log.d(THIS_FILE, "Starting ringer...");
                int mode = DeviceInfo.getInfo().getRingerMode();
                audioManager.setMode(mode);
                ringerWorker.sendMessage(msg);
            }
        }

        /**
         * @param ringtone
         */
        public synchronized void setRingtone(Ringtone ringtone) {
            if(this.ringtone != null) {
                this.ringtone.stop();
            }
            this.ringtone = ringtone;
            askedStopped = false;
        }

        public synchronized void askStop() {
            askedStopped = true;
        }
        
        public synchronized boolean isStopped() {
            return askedStopped || (ringtone == null);
        }

        public void handleMessage(Message msg) {
            if(ringtone == null) {
                return;
            }
            if (msg.arg1 == PROGRESS_RING
                    || msg.arg1 == PROGRESS_NOTIFY) {
                synchronized (askedStopped) {
                    if(askedStopped) {
                        ringtone.stop();
                        ringtone = null;
                        return;
                    }
                }
                
                if(!ringtone.isPlaying()) {
                    ringtone.play();
                }

                if(msg.arg1 == PROGRESS_RING) {
                    Message msgBis = ringerWorker.obtainMessage(PROGRESS_RING);
                    msg.arg1 = PROGRESS_RING;
                    ringerWorker.sendMessageDelayed(msgBis, 100);
                }
                else{
                    stopRing();
                }
            }
        }
    }

    private Ringtone getRingtone(String defaultRingtone) {
    	Uri ringtoneUri = Uri.parse(defaultRingtone);
		return RingtoneManager.getRingtone(context, ringtoneUri);
    }
}
